<?php

namespace openai;


class ChatGPT {

    private $api_url = 'https://api.openai.com/v1/chat/completions';
	private $api_key = '';
	private $streamHandler;
	private $question;
    private $dfa = NULL;
    private $check_sensitive = false;

    private $messageText = '';

	public function __construct($params) {
        $this->api_key = $params['api_key'] ?? '';
    }

    public function set_dfa(&$dfa){
        $this->dfa = $dfa;
        if(!empty($this->dfa) && $this->dfa->is_available()){
            $this->check_sensitive = TRUE;
        }
    }

    public function qa($params, $messages = [])
    {
        // 这行代码用于关闭输出缓冲。关闭后，脚本的输出将立即发送到浏览器，而不是等待缓冲区填满或脚本执行完毕。
        ini_set('output_buffering', 'off');
        // 这行代码禁用了 zlib 压缩。通常情况下，启用 zlib 压缩可以减小发送到浏览器的数据量，但对于服务器发送事件来说，实时性更重要，因此需要禁用压缩。
        ini_set('zlib.output_compression', false);
        // 这行代码使用循环来清空所有当前激活的输出缓冲区。ob_end_flush() 函数会刷新并关闭最内层的输出缓冲区，@ 符号用于抑制可能出现的错误或警告。
        while (@ob_end_flush()) {}
        // 这行代码设置 HTTP 响应的 Content-Type 为 text/event-stream，这是服务器发送事件（SSE）的 MIME 类型。
        header('Content-Type: text/event-stream');
        // 这行代码设置 HTTP 响应的 Cache-Control 为 no-cache，告诉浏览器不要缓存此响应。
        header('Cache-Control: no-cache');
        // 这行代码设置 HTTP 响应的 Connection 为 keep-alive，保持长连接，以便服务器可以持续发送事件到客户端。
        header('Connection: keep-alive');
        // 这行代码设置 HTTP 响应的自定义头部 X-Accel-Buffering 为 no，用于禁用某些代理或 Web 服务器（如 Nginx）的缓冲。
        // 这有助于确保服务器发送事件在传输过程中不会受到缓冲影响。
        header('X-Accel-Buffering: no');
        //echo 'data: '.json_encode(['time'=>date('Y-m-d H:i:s'), 'content'=>'']).PHP_EOL.PHP_EOL;
        //ob_flush();
        //flush();


        $this->question = $params['question'];
        $this->streamHandler = new StreamHandler([
            'qmd5' => md5($this->question.''.time())
        ]);
//        if($this->check_sensitive){
//            $this->streamHandler->set_dfa($this->dfa);
//        }
//
//        if(empty($this->api_key)){
//            $this->streamHandler->end('OpenAI 的 api key 还没填');
//            return;
//        }
//
//        // 开启检测且提问包含敏感词
//        if($this->check_sensitive && $this->dfa->containsSensitiveWords($this->question)){
//            $this->streamHandler->end('您的问题不合适，AI暂时无法回答');
//            return;
//        }

//    	$messages = [
//    	    [
//    	        'role' => 'system',
//    	        'content' => $params['system'] ?? '',
//    	    ],
//    	    [
//    	        'role' => 'user',
//    	        'content' => $this->question
//    	    ]
//    	];

    	$json = json_encode([
    	    'model' => 'gpt-3.5-turbo-0613',
    	    'messages' => $messages,
    	    'temperature' => 0.6,
    	    'stream' => true,
    	]);

    	$headers = array(
    	    "Content-Type: application/json",
    	    "Authorization: Bearer ".$this->api_key,
    	);

    	$this->openai($json, $headers);
        // 获取消息文本
        $this->messageText = $this->streamHandler->getMessageText();
    }

    // 获取Chat回答
    public function getAnswer()
    {
        return  $this->messageText;
    }

    private function openai2($json, $headers)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->api_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
//        	curl_setopt($ch, CURLOPT_WRITEFUNCTION, [$this->streamHandler, 'callback']);


        // 创建一个临时文件来保存响应数据
        $tempFile = tmpfile();
        curl_setopt($ch, CURLOPT_FILE, $tempFile);

         $response = curl_exec($ch);

        // 从临时文件中读取响应数据
        rewind($tempFile);
        $generatedText = stream_get_contents($tempFile);

        // 关闭 cURL 请求和临时文件
        curl_close($ch);
        fclose($tempFile);

// 提取 content 字段并拼接成一句话
//        if (isset($response['choices'][0]['text'])) {
//            $content = $response['choices'][0]['text'];
//            $sentence = implode(' ', $content);
//            echo 'Generated Sentence: ' . $sentence;
//        } else {
//            echo 'Failed to generate sentence';
//        }

        die($generatedText);

    }

    private function openai($json, $headers)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $this->api_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    	curl_setopt($ch, CURLOPT_WRITEFUNCTION, [$this->streamHandler, 'callback']);
        $response = curl_exec($ch);

        if(curl_errno($ch)) {
            //file_put_contents('./log/curl.error.log', curl_error($ch).PHP_EOL.PHP_EOL, FILE_APPEND);
        }

        curl_close($ch);
    }

}

